﻿/// <reference path="../jquery-1.4.1-vsdoc.js" />

(function ($) {


	$.fn.ShExpandList = function (method) {

		var settings = {
			onInit: null,
			onShow: null,
			onHide: null,
			onToggle: null,
			onBeforeShow: null,
			onBeforeHide: null,
			guts: '>.guts',
			src: '>.h',
			state: null
		};

		var methods = {
			init: function (options) {

				if (options) {
					$.extend(settings, options);
				}


				return this.each(function () {

					var $this = $(this),
					 data = $this.data('shexpandlist');

					// If the plugin hasn't been initialized yet
					if (!data) {

						// find head class, wire to onclick, show hide guts, w bass
						var $src = $this.find(settings.src),
							$guts = $this.find(settings.guts);

						$src.click(function (e) {

							// dont call toggle if beforeshow is set, let before show take care of it
							if (($guts.is(":visible") && !settings.onBeforeHide)
								|| (!$guts.is(":visible") && !settings.onBeforeShow)) {
								methods.toggle.call($this);
								e.preventDefault();
							} else {
								// fire onbeforeshow or onbeforehide instead
								if (!$guts.is(":visible"))
									(settings.onBeforeShow) ? settings.onBeforeShow($this) : null;
								else
									(settings.onBeforeHide) ? settings.onBeforeHide($this) : null;
							}


						});
						// save the element, the list and the hidden field in data for later use
						$this.data('shexpandlist', {
							target: $this,
							onShow: settings.onShow,
							onHide: settings.onHide,
							onToggle: settings.onToggle,
							onBeforeShow: settings.onBeforeShow,
							onBeforeHide: settings.onBeforeHide,
							onInit: settings.onInit,
							guts: settings.guts,
							gutsElement: $guts,
							src: settings.src,
							srcElement: $src,
							state: settings.state
						});
						// add onload
						if (settings.onInit) settings.onInit.call($this, $this.data('shexpandlist'));

						// if to show show by default
						if ($this.attr("data-state") == "show" || settings.state == "show") {
							methods.show.call($this);
						} else {
							methods.hide.call($this);
						}


					}
				});


			},
			show: function () {

				// show , if onToggle is defined, i should find out whether to call it or not according to what? visible state
				var s = this.data('shexpandlist');

				if (!s.gutsElement.is(":visible")) {

					(s.onToggle) ? s.onToggle.call(this, s) : null; // fire toggle
					s.gutsElement.slideDown("fast"); // show

				}
				(s.onShow) ? s.onShow.call(this, s) : null; // fire onshow anyway
				return this;

			},
			toggle: function () {
				var $t = this,
				s = this.data('shexpandlist');
				s.gutsElement.slideToggle("fast", function () {
					// if showing, fire onshow sa7?

					if ($(this).is(":visible")) {
						(s.onShow) ? s.onShow.call($t, s) : null;

					} else {
						(s.onHide) ? s.onHide.call($t, s) : null;
					}
				});
				(s.onToggle) ? s.onToggle.call(this, s) : null;
				return this;

			},
			hide: function () {
				var s = this.data('shexpandlist');
				if (s.gutsElement.is(":visible")) {
					(s.onToggle) ? s.onToggle.call(this, s) : null; // fire toggle
					s.gutsElement.slideUp("fast");
				}

				(s.onHide) ? s.onHide.call(this, s) : null;
				return this;
			}

		};

		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('Method ' + method + ' does not exist');
		}



	};


})(jQuery);
